/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */
 
#include "dbus-stuff.h"
#include "dbsqlite.h"
#include <string.h>
#include <E_DBus.h>
#include <Elementary.h>

int ring_vol = 0, vibrate = 0, in_calls=0, m_calls=0, m_sms=0, bb_count=0;
char *query, *query_sms, *query_calls, msg_tone[255], add_sms[255], *add_sms_path = add_sms;

void dbus_reply_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
}

void vol_reply_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, variant;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	dbus_message_iter_recurse(&iter, &variant);
	dbus_message_iter_get_basic(&variant, &ring_vol);
}

void vib_reply_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, variant;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	dbus_message_iter_recurse(&iter, &variant);
	dbus_message_iter_get_basic(&variant, &vibrate);
}

void tone_reply_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, variant;
	char tone[255];
	char *to = &tone[0];
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	dbus_message_iter_recurse(&iter, &variant);
	dbus_message_iter_get_basic(&variant, &to);
	sprintf(msg_tone, "/usr/share/sounds/%s", to);
}

void play_noti_snd(void)
{
	DBusMessage *msg;
	int val1, val2;
	
	msg = dbus_message_new_method_call(
		"org.freesmartphone.odeviced",
		"/org/freesmartphone/Device/Audio",
		"org.freesmartphone.Device.Audio",
		"PlaySound"
	);
	//set value based on users msg ring tone
	const char *value = msg_tone;
	val1 = 0; val2 = 10;
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INT32, &val1, DBUS_TYPE_INT32, &val2, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);	
}

void vibrate_phone(void)
{
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.odeviced",
		"/org/freesmartphone/Device/LED/neo1973_vibrator",
		"org.freesmartphone.Device.LED",
		"BlinkSeconds"
	);
	int val1 = 1, val2 = 250, val3 = 2000;
	dbus_message_append_args (msg, DBUS_TYPE_INT32, &val1, DBUS_TYPE_INT32, &val2,DBUS_TYPE_INT32, &val3, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);	
}

int reminder_func(void *data)
{
	//remind the user - clear after click on sms/missed call icon
	if(ring_vol > 0) {
   		if (pend_call || pend_sms || pend_noti) play_noti_snd();
    }
	if(vibrate) vibrate_phone();
	return 1;
}

void
cb_request_name(void *data, DBusMessage *msg, DBusError *err)
{
	// TODO:check that this actually succeeded and handle errors...
	//printf("request name\n");
}

DBusMessage *
cb_alarm(E_DBus_Object *obj, DBusMessage *msg)
{
	DBusMessage *reply;
	int t=0;
	
    //check and set next alarm
	reload_alarms(&t);
	
	reply = dbus_message_new_method_return(msg);
	return reply;
}

DBusMessage *
cb_reload_alarmtimes(E_DBus_Object *obj, DBusMessage *msg)
{
	DBusMessage *reply;
	int t=0;
	
	printf("Reloading Alarms\n");
    //check and set next alarm
	reload_alarms(&t);
	
	reply = dbus_message_new_method_return(msg);
	return reply;
}

void clear_suspend_timer(void)
{
	DBusMessage *msg;
	msg = dbus_message_new_method_call("org.freesmartphone.otimed",
		"/org/freesmartphone/Time/Alarm", "org.freesmartphone.Time.Alarm",
		"ClearAlarm");
	const char *value = "org.launcher.alarm";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void set_wake_timer(int tim)
{
	DBusMessage *msg;

	clear_suspend_timer();
	msg = dbus_message_new_method_call("org.freesmartphone.otimed",
		"/org/freesmartphone/Time/Alarm", "org.freesmartphone.Time.Alarm",
		"SetAlarm");
	const char *value = "org.launcher.alarm";
	dbus_message_append_args(msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INT32, &tim, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void init_dbus_stuff(void)
{
	char db[255];
	int db_ret, co=0;
	E_DBus_Object *alarm;
	E_DBus_Interface *iface;
	DBusMessage *msg;
	//get the users home directory
	const char *name = "HOME";
	sprintf(launcher_dir, "%s", getenv(name));
	//connect to launcher db
	sprintf(db, "%s/.launcher/launcher.db", launcher_dir);
	db_ret = sqlite3_open(db, &launcher_thread);
	e_dbus_init();
	conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
	if (!conn) {
		printf("Error connecting to system bus.");
		exit(1);
	}

	//check if contacts already synced
	co = get_contacts_count_db();
	//TODO : check for number of contacts to see if new added or deleted
	if(!co) get_all_contacts(); //gets contacts data and then sms data
	else get_sms_data(); //skips syncing contacts
	get_calls_data();//generally takes the longest to respond

	//get dbus data on radios and brightness
	get_brightness();
	get_gps_status();
	get_gsm_status();
	get_wifi_status();
	get_bt_status();
	
	//set the interface to receive alarms
	//create an xml file and add it to /etc/dbus-1/system.d/launcher-alarm.conf
	e_dbus_request_name(conn, "org.launcher.alarm", 0, cb_request_name, NULL);
	alarm = e_dbus_object_add(conn, "/", NULL);
	iface = e_dbus_interface_new("org.freesmartphone.Notification");
	e_dbus_interface_method_add(iface, "Alarm", NULL, NULL, cb_alarm);
	e_dbus_object_interface_attach(alarm, iface);

	//set the interface to receive alarm reload signals
	//edit the xml file at /etc/dbus-1/system.d/launcher-alarm.conf
	iface = e_dbus_interface_new("org.freesmartphone.Reload");
	e_dbus_interface_method_add(iface, "AlarmTimes", NULL, NULL, cb_reload_alarmtimes);
	e_dbus_object_interface_attach(alarm, iface);
		
	//listen for calls
	e_dbus_signal_handler_add(conn, "org.freesmartphone.opimd", 
	                          "/org/freesmartphone/PIM/Calls", "org.freesmartphone.PIM.Calls", 
	                          "NewCall", ind_missed, NULL);
	//listen for sms
	e_dbus_signal_handler_add(conn, "org.freesmartphone.opimd", 
	                          "/org/freesmartphone/PIM/Messages", "org.freesmartphone.PIM.Messages", 
	                          "NewMessage", ind_sms, NULL);
	//listen for contacts
	e_dbus_signal_handler_add(conn, "org.freesmartphone.opimd", 
	                          "/org/freesmartphone/PIM/Contacts", "org.freesmartphone.PIM.Contacts", 
	                          "NewContact", ind_new_contact, NULL);
	//listen for cell broadcast
	e_dbus_signal_handler_add(conn, "org.freesmartphone.ogsmd", 
                               "/org/freesmartphone/GSM/Device", "org.freesmartphone.GSM.CB", 
                               "IncomingCellBroadcast", ind_cb, NULL);
	//set subscription for cb channels
	msg = dbus_message_new_method_call("org.freesmartphone.ogsmd",
		"/org/freesmartphone/GSM/Device", "org.freesmartphone.GSM.CB",
		"SetCellBroadcastSubscriptions");
	const char *value = cb_subs;
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
	//listen for resume - bt headset stuff
	e_dbus_signal_handler_add(conn, "org.freesmartphone.ousaged", 
                               "/org/freesmartphone/Usage", "org.freesmartphone.Usage", 
                               "SystemAction", ind_sys, NULL);
	//get ring volume
	msg = dbus_message_new_method_call("org.freesmartphone.opreferencesd",
		"/org/freesmartphone/Preferences/phone", "org.freesmartphone.Preferences.Service",
		"GetValue");
	value = "ring-volume";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, vol_reply_cb, -1, NULL);
	//get vibration setting
	msg = dbus_message_new_method_call("org.freesmartphone.opreferencesd",
		"/org/freesmartphone/Preferences/phone", "org.freesmartphone.Preferences.Service",
		"GetValue");
	value = "ring-vibration";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, vib_reply_cb, -1, NULL);
	//get message-tone
	msg = dbus_message_new_method_call("org.freesmartphone.opreferencesd",
		"/org/freesmartphone/Preferences/phone", "org.freesmartphone.Preferences.Service",
		"GetValue");
	value = "message-tone";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, tone_reply_cb, -1, NULL);
	dbus_message_unref(msg);	
	
	printf("dbus init over. opim data pending......\n");
	elm_win_title_set(win, "Launcher");
}

void ind_sys(void *data, DBusMessage *msg)
{
	time_t tim;
	int t;
	char mess[255], *b_message = mess, path[255];
	DBusError *error=NULL;
	
	dbus_message_get_args(msg, error,
	                      DBUS_TYPE_STRING, &b_message,
	                      DBUS_TYPE_INVALID);
	if(strcmp(b_message, "resume") == 0){
		if (reconnect_bt) {
			//connect the bt headset
			sprintf(path, "/org/bluez/%d/hci0/dev_%s", pidof_btd, hs_add);
			msg = dbus_message_new_method_call("org.bluez", path, "org.bluez.Headset", "Connect");
			e_dbus_message_send(conn, msg, vib_reply_cb, -1, NULL);
		}
		if (pend_call || pend_sms || pend_noti) {
			play_noti_snd();
		    reminder_timer = ecore_timer_add(120.0, reminder_func, NULL);
		}
	}
    if(strcmp(b_message, "suspend") == 0){
        //del local timer
	    if (reminder_timer) ecore_timer_del(reminder_timer);
		//set new alarm
		time(&tim);
		t = tim + 300;
		reload_alarms(&t);
    }
}

void ind_cb(void *data, DBusMessage *msg)
{
	int channel;
	char mess[255], *b_message = mess, temp[25], ty[25];
	DBusError *error=NULL;
	
	dbus_message_get_args(msg, error,
	                      DBUS_TYPE_INT32, &channel,
	                      DBUS_TYPE_STRING, &b_message,
	                      DBUS_TYPE_INVALID);
	//create the message
	if (show_c_no) sprintf(temp, "%d - %s", channel, b_message);
	else strcpy(temp, b_message);
	printf("%s\n", b_message);
	if (strlen(temp) < 20) elm_label_label_set(lb_loc, temp);
	else {
		strncpy(ty, temp, 20);
		strcat(ty, "...");
		elm_label_label_set(lb_loc, ty);
	}
	//put the mesasge in the database
	insert_location(temp);
}

void handle_call_data(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, array, dict, final;
	int type, index, out;
	char key_val[255], *key = key_val, val[255], *str_val = val, buf[255], tystr[4], n[255], *na=n;
	dbus_int32_t int_val;
	_call_data Call;

	if (!dbus_message_iter_init(replymsg, &array)) printf("Message has no arguments");
	if ((type = dbus_message_iter_get_arg_type (&array)) != DBUS_TYPE_INVALID) //array
		dbus_message_iter_recurse(&array, &dict); //dict entry 
	while ((type = dbus_message_iter_get_arg_type (&dict)) != DBUS_TYPE_INVALID) {
			dbus_message_iter_recurse(&dict, &iter);
			dbus_message_iter_get_basic(&iter, &key);
			dbus_message_iter_next(&iter);
			dbus_message_iter_recurse(&iter, &final);
			type = dbus_message_iter_get_arg_type (&final);
			if (type == DBUS_TYPE_STRING) {
				dbus_message_iter_get_basic(&final, &str_val);
				//printf("%s:%s\n", key, str_val);
			}
			else if (type == DBUS_TYPE_INT32) {
				dbus_message_iter_get_basic(&final, &int_val);
				//printf("%s:%d\n", key, int_val);
			}
			if (strcmp(key, "Peer") == 0) strcpy(Call.peer, str_val);
			if (strcmp(key, "Timestamp") == 0) Call.timestamp = int_val;
			if (strcmp(key, "Direction") == 0) strcpy(Call.direction, str_val);
			if (strcmp(key, "Duration") == 0) Call.duration = int_val;
			if (strcmp(key, "Answered") == 0) Call.ans = int_val;
			if (strcmp(key, "Replied") == 0) Call.replied = int_val;
			if (strcmp(key, "New") == 0) Call.new_call = int_val;
			if (strcmp(key, "Path") == 0) strcpy(Call.path, str_val);
			dbus_message_iter_next(&dict); //while part
		}
	index = insert_calls_data(&Call);
	update_state_time(Call.timestamp, "calltime");
	match_call_name(Call.peer, index, na);
	//indicate call if missed
	if ((strcmp(Call.direction, "in") ==0) && (Call.ans == 0)) {
		m_calls ++;
		snprintf(buf, sizeof(buf), "%s/missed.png", "/usr/share/launcher");
		elm_icon_file_set(ic_calls, buf, NULL);
		elm_icon_scale_set(ic_calls, 1, 1);
		evas_object_size_hint_min_set(ic_calls, 70, 70);
		//set the no of calls missed
		sprintf(tystr, "%d", m_calls);
		edje_object_part_text_set(main_edje, "no_calls", tystr);
		//set reminder
		if (!reminder_timer) reminder_timer = ecore_timer_add(120.0, reminder_func, NULL);
		pend_call = 1;
	}
	//update contact data for last outgoing call
	if (Call.ans == 1) {
		if(strcmp(Call.direction, "out") ==0) out = 1;
		else out = 0;
		update_contact_last("call", Call.timestamp, out, na);
	}
}

void handle_sms_data(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, array, dict, final;
	int type, index;
	char key_val[255], *key = key_val, val[255], *str_val = val, buf[255], tystr[20], n[255], *na=n;
	char *tok, ty[255];
	dbus_int32_t int_val;
	_sms_data SMS;
	
	if (!dbus_message_iter_init(replymsg, &array)) printf("Message has no arguments");
	if ((type = dbus_message_iter_get_arg_type (&array)) != DBUS_TYPE_INVALID) //array
		dbus_message_iter_recurse(&array, &dict); //dict entry 
	while ((type = dbus_message_iter_get_arg_type (&dict)) != DBUS_TYPE_INVALID) {
		dbus_message_iter_recurse(&dict, &iter);
		dbus_message_iter_get_basic(&iter, &key);
		dbus_message_iter_next(&iter);
		dbus_message_iter_recurse(&iter, &final);
		type = dbus_message_iter_get_arg_type (&final);
		if (type == DBUS_TYPE_STRING) dbus_message_iter_get_basic(&final, &str_val);
		else if (type == DBUS_TYPE_INT32) dbus_message_iter_get_basic(&final, &int_val);
		if (strcmp(key, "Direction") == 0) strcpy(SMS.direction, str_val);
		else if (strcmp(key, "Sender") == 0) strcpy(SMS.sender, str_val);
		else if (strcmp(key, "Recipient") == 0) strcpy(SMS.recipient, str_val);
		else if (strcmp(key, "SMS-combined_message") ==0) SMS.combined = int_val;
		else if (strcmp(key, "Timestamp") ==0) SMS.timestamp = int_val;
		else if (strcmp(key, "Content") ==0) strcpy(SMS.content, str_val);
		else if (strcmp(key, "MessageRead") ==0) SMS.read = int_val;
		else if (strcmp(key, "MessageSent") ==0) SMS.sent = int_val;
		else if (strcmp(key, "Combined") ==0) SMS.combined = int_val;
		else if (strcmp(key, "Path") ==0) strcpy(SMS.path, str_val);
		dbus_message_iter_next(&dict); //while part
	}
	//remove prefix from sender
	strcpy(ty, SMS.sender);
	tok = strchr(ty, ':');
	if(tok != NULL) {
		tok = strtok(ty, ":");
		tok = strtok(NULL, ":");
		strcpy(SMS.sender, tok);
	}
	//remove prefix from recipient
	strcpy(ty, SMS.recipient);
	tok = strchr(ty, ':');
	if(tok != NULL) {
		tok = strtok(ty, ":");
		tok = strtok(NULL, ":");
		strcpy(SMS.recipient, tok);
	}
	index = insert_sms_data(&SMS);
	update_state_time(SMS.timestamp, "smstime");
	if (strcmp(SMS.direction, "in") == 0) match_sms_name(SMS.sender, index, na);
	else match_sms_name(SMS.recipient, index, na);

	if(strcmp(SMS.direction, "in") == 0) {
		m_sms++;
		snprintf(buf, sizeof(buf), "%s/sms.png", "/usr/share/launcher");
		elm_icon_file_set(ic_sms, buf, NULL);
		elm_icon_scale_set(ic_sms, 1, 1);
		evas_object_size_hint_min_set(ic_sms, 70, 70);
		//set the no of calls missed
		sprintf(tystr, "%d", m_sms);
		edje_object_part_text_set(main_edje, "no_sms", tystr);
		//set reminder
		if (!reminder_timer) reminder_timer = ecore_timer_add(120.0, reminder_func, NULL);
		pend_sms = 1;
		update_contact_last("sms", SMS.timestamp, 0, na);
	}
	//if(win_conv) add_sms_conv (); - causing segmentation fault
	//refresh bubbles if win_sms open and relevant sms comes in
}
//sms's sent to myself are not being shown as received!!
void ind_sms(void *data, DBusMessage *msg)
{
	char  path[255], *ty = path;
	DBusError *error=NULL;

	dbus_message_get_args(msg, error,
	                      DBUS_TYPE_STRING, &ty,
	                      DBUS_TYPE_INVALID);
	//get sms data
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		ty,
		"org.freesmartphone.PIM.Message",
		"GetContent"
	);
	e_dbus_message_send(conn, msg, handle_sms_data, -1, NULL);
	dbus_message_unref(msg);
}

void ind_missed(void *data, DBusMessage *msg)
{
	char path[255], *ty = path;
	DBusError *error=NULL;

	dbus_message_get_args(msg, error,
	                      DBUS_TYPE_STRING, &ty,
	                      DBUS_TYPE_INVALID);
	//get call data
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		ty,
		"org.freesmartphone.PIM.Call",
		"GetContent"
	);
	e_dbus_message_send(conn, msg, handle_call_data, -1, NULL);
	dbus_message_unref(msg);
}

void handle_contact_data(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, array, dict, final;
	int type;
	char key_val[255], *key = key_val, val[255], *str_val = val;
	_contact con;
	
	if (!dbus_message_iter_init(replymsg, &array)) printf("Message has no arguments");
	if ((type = dbus_message_iter_get_arg_type (&array)) != DBUS_TYPE_INVALID) //array
		dbus_message_iter_recurse(&array, &dict); //dict entry 
	while ((type = dbus_message_iter_get_arg_type (&dict)) != DBUS_TYPE_INVALID) {
			dbus_message_iter_recurse(&dict, &iter);
			dbus_message_iter_get_basic(&iter, &key);
			dbus_message_iter_next(&iter);
			dbus_message_iter_recurse(&iter, &final);
			type = dbus_message_iter_get_arg_type (&final);
			if (type == DBUS_TYPE_STRING) {
				dbus_message_iter_get_basic(&final, &str_val);
				//printf("%s:%s\n", key, str_val);
			}
			if (strcmp(key, "Name") == 0) strcpy(con.name, str_val);
			else if (strcmp(key, "Path") == 0) strcpy(con.path, str_val);
			else if (strcmp(key, "Phone") == 0) strcpy(con.phone, str_val);
			dbus_message_iter_next(&dict); //while part
		}
	insert_contact_data(&con);
	match_call_names ();
	match_sms_names ();
}

void ind_new_contact(void *data, DBusMessage *msg)
{
	char path[255], *ty = path;
	DBusError *error=NULL;

	dbus_message_get_args(msg, error,
	                      DBUS_TYPE_STRING, &ty,
	                      DBUS_TYPE_INVALID);
	//get call data
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		ty,
		"org.freesmartphone.PIM.Contact",
		"GetContent"
	);
	e_dbus_message_send(conn, msg, handle_contact_data, -1, NULL);
	dbus_message_unref(msg);
}
/*
void cb_request_name(void *data, DBusMessage *msg, DBusError *err)
{
  // XXX check that this actually succeeded and handle errors...
  printf("request name\n");
}

//method callback
DBusMessage *cb_notify(E_DBus_Object *obj, DBusMessage *msg)
{
	char noti_app[255], noti_mess[255], noti_launch[255];
	DBusError *error=NULL;

	dbus_message_get_args(msg, error,
	                      DBUS_TYPE_STRING, &noti_app,
	                      DBUS_TYPE_STRING, &noti_mess,
	                      DBUS_TYPE_STRING, &noti_launch,
	                      DBUS_TYPE_INVALID);
	printf("%s %s %s\n", noti_app, noti_mess, noti_launch);
	return 0;
}

//start the notification service
int start_noti_service(void)
{
	E_DBus_Object *notify;
	E_DBus_Interface *iface;

	e_dbus_request_name(conn, "launcher.c.Notify", 0, cb_request_name, NULL);
	notify = e_dbus_object_add(conn, "/launcher/c/Notify", NULL);
	iface = e_dbus_interface_new("launcher.c.Notify");
	e_dbus_interface_method_add(iface, "Notify", NULL, NULL, cb_notify);
	e_dbus_object_interface_attach(notify, iface);
	return 1;
}
*/
void populate_sms_table(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, array, array2, dict, variant;
	int type;
	char key_val[255], *key = key_val, val[510], *str_val = val, *tok, ty[255];
	dbus_int32_t int_val;
	_sms_data SMS;

	if (dbus_error_is_set(error)) {
		printf("SMS Data Error: %s - %s\n", error->name, error->message);
		return;
	}
	printf("Updating SMS data..\n");
	begin_transaction();
	if (!dbus_message_iter_init(replymsg, &array)) {
		printf("Message has no arguments");
		return;
	}
	if ((type = dbus_message_iter_get_arg_type (&array)) != DBUS_TYPE_INVALID) //aray
		dbus_message_iter_recurse(&array, &array2); //array
	while((type = dbus_message_iter_get_arg_type (&array2)) != DBUS_TYPE_INVALID) {
			dbus_message_iter_recurse(&array2, &dict);//dict type entry as string
		while((type = dbus_message_iter_get_arg_type (&dict)) != DBUS_TYPE_INVALID) {
			dbus_message_iter_recurse(&dict, &iter);//string
			dbus_message_iter_get_basic(&iter, &key);
			if (dbus_message_iter_has_next(&iter)) dbus_message_iter_next(&iter);
			dbus_message_iter_recurse(&iter, &variant);
			type = dbus_message_iter_get_arg_type (&variant);
			if (type == DBUS_TYPE_STRING) dbus_message_iter_get_basic(&variant, &str_val);
			else if (type == DBUS_TYPE_INT32) dbus_message_iter_get_basic(&variant, &int_val);
			if (strcmp(key, "Direction") == 0) strcpy(SMS.direction, str_val);
			else if (strcmp(key, "Sender") == 0) strcpy(SMS.sender, str_val);
			else if (strcmp(key, "Recipient") == 0) strcpy(SMS.recipient, str_val);
			else if (strcmp(key, "SMS-combined_message") ==0) SMS.combined = atoi(str_val);
			else if (strcmp(key, "Timestamp") ==0) SMS.timestamp = int_val;
			else if (strcmp(key, "Content") ==0) strcpy(SMS.content, str_val);
			else if (strcmp(key, "MessageRead") ==0) SMS.read = int_val;
			else if (strcmp(key, "MessageSent") ==0) SMS.sent = int_val;
			else if (strcmp(key, "Path") ==0) strcpy(SMS.path, str_val);
			dbus_message_iter_next(&dict);
		}
	//remove prefix from sender
	strcpy(ty, SMS.sender);
	tok = strchr(ty, ':');
	if(tok != NULL) {
		tok = strtok(ty, ":");
		tok = strtok(NULL, ":");
		strcpy(SMS.sender, tok);
	}
	//remove prefix from recipient
	strcpy(ty, SMS.recipient);
	tok = strchr(ty, ':');
	if(tok != NULL) {
		tok = strtok(ty, ":");
		tok = strtok(NULL, ":");
		strcpy(SMS.recipient, tok);
	}
	insert_sms_data(&SMS);
	dbus_message_iter_next(&array2);
	}
	commit_transaction();
	//delete the query object
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query_sms,
		"org.freesmartphone.PIM.MesasgeQuery",
		"Dispose"
	);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	match_sms_names();
	update_sms_timestamp();
}

void sms_reply_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	char tystr[255];
	query = tystr;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_STRING, &query, DBUS_TYPE_INVALID);
	printf("%s\n", query);

	//get last 20 calls from the query location
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query,
		"org.freesmartphone.PIM.MessageQuery",
		"GetMultipleResults"
	);
	int value = 20;
	dbus_message_append_args (msg, DBUS_TYPE_INT32, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, populate_sms_table, -1, NULL);
	dbus_message_unref(msg);
}

void place_call(char *num)
{
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.ogsmd",
		"/org/freesmartphone/GSM/Device",
		"org.freesmartphone.GSM.Call",
		"Initiate"
	);
	//set value based on users msg ring tone
	char *type = "voice";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &num, DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void update_sync_status_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	if (dbus_error_is_set(error)) {
		printf("sync add Error: %s - %s\n", error->name, error->message);
	}
	//dbus_message_get_args(replymsg, NULL, DBUS_TYPE_STRING, &query, DBUS_TYPE_INVALID);
	else printf("Updated..\n");
}

void update_sync_status(char *pa)
{
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;
	char key_val[255], *key = key_val;
	int int_val = 1;
	
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		pa,
		"org.freesmartphone.PIM.Contact",
		"Update"
	);
	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	
	key = "Sync";
	dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
			dbus_message_iter_close_container(&dict, &variant);
		dbus_message_iter_close_container(&array, &dict);
	dbus_message_iter_close_container(&iter, &array);
	e_dbus_message_send(conn, msg, update_sync_status_cb, -1, NULL);
	dbus_message_unref(msg);	
}

void populate_contacts_table(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, array, dict, variant, final;
	int type, int_val=2;
	char key_val[255], ty[255], *key = key_val, val[255], *str_val = val;
	_contact con;

	if (dbus_error_is_set(error)) {
		printf("Contacts SMS Data Error: %s - %s\n", error->name, error->message);
		return;
	}	
	//elm_win_title_set(win, "Updating Contacts Data..");
	printf("Updating Contacts Data..\n");
	begin_transaction();
	//we need the tel no, time and duration to be shown
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	if ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
		dbus_message_iter_recurse(&iter, &array);
	while((type = dbus_message_iter_get_arg_type (&array)) != DBUS_TYPE_INVALID) {
		dbus_message_iter_recurse(&array, &dict);
		while((type = dbus_message_iter_get_arg_type (&dict)) != DBUS_TYPE_INVALID) {
			dbus_message_iter_recurse(&dict, &variant);
			dbus_message_iter_get_basic(&variant, &key);
			sprintf(ty, "%s", key);
			if (dbus_message_iter_has_next(&variant)) dbus_message_iter_next(&variant);
			dbus_message_iter_recurse(&variant, &final);
			if ((type = dbus_message_iter_get_arg_type (&final)) == DBUS_TYPE_STRING)
				dbus_message_iter_get_basic(&final, &str_val);
			else if ((type = dbus_message_iter_get_arg_type (&final)) == DBUS_TYPE_INT32)
				dbus_message_iter_get_basic(&final, &int_val);
			if (strcmp(key, "Name") == 0) strcpy(con.name, str_val);
			else if (strcmp(key, "Path") == 0) strcpy(con.path, str_val);
			else if (strcmp(key, "Phone") == 0) strcpy(con.phone, str_val);
			else if (strcmp(key, "Category") == 0) strcpy(con.cat, str_val);
			else if (strcmp(key, "email") == 0) strcpy(con.email, str_val);
			else if (strcmp(key, "Birthday") == 0) strcpy(con.bday, str_val);
			else if (strcmp(key, "Anniversary") == 0) strcpy(con.anniv, str_val);
			dbus_message_iter_next (&dict);
		}
		insert_contact_data(&con);
		//if(int_val == 2) update_sync_status(con.path);
		//else int_val = 2;
		dbus_message_iter_next (&array);
	}	
	commit_transaction();
	//delete the query object
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query,
		"org.freesmartphone.PIM.ContactQuery",
		"Dispose"
	);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	elm_win_title_set(win, "Launcher");
	get_sms_data();
}

void get_all_contacts(void)
{
	DBusMessage *msg;
	DBusMessageIter iter, array, dict;
	
	printf("Getting All Contacts data..\n");
	msg = dbus_message_new_method_call(
		    "org.freesmartphone.opimd",
		    "/org/freesmartphone/PIM/Contacts",
		    "org.freesmartphone.PIM.Contacts",
		    "Query"
	);
	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	dbus_message_iter_close_container(&iter, &array);

	e_dbus_message_send(conn, msg, get_contacts_count, -1, NULL);
	dbus_message_unref(msg);
}

void get_contacts_results(void *data, DBusMessage *replymsg, DBusError *error)
{
	int co=0;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	//if (!co) get_all_contacts();
	else {
		dbus_message_get_args(replymsg, NULL, DBUS_TYPE_INT32, &co, DBUS_TYPE_INVALID);
		DBusMessage *msg;
		msg = dbus_message_new_method_call(
			"org.freesmartphone.opimd",
			query,
			"org.freesmartphone.PIM.ContactQuery",
			"GetMultipleResults"
		);
		dbus_message_append_args (msg, DBUS_TYPE_INT32, &co, DBUS_TYPE_INVALID);
		e_dbus_message_send(conn, msg, populate_contacts_table, -1, NULL);
		dbus_message_unref(msg);
	}
}

void get_contacts_count(void *data, DBusMessage *replymsg, DBusError *error)
{
	char q[255], *q_co=q;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_STRING, &q_co, DBUS_TYPE_INVALID);
	query = strdup(q_co);
		
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query,
		"org.freesmartphone.PIM.ContactQuery",
		"GetResultCount"
	);
	e_dbus_message_send(conn, msg, get_contacts_results, -1, NULL);
	dbus_message_unref(msg);
}

void get_contacts_data (void)
{
	get_all_contacts();
	/*char k[255], *key = k;
	int int_val=1;
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;

	//printf("Getting Contacts data..\n");
	//elm_win_title_set(win, "Getting Contacts data..");
	
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		"/org/freesmartphone/PIM/Contacts",
		"org.freesmartphone.PIM.Contacts",
		"Query"
	);
	key = "_lt_Sync";
	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
			dbus_message_iter_close_container(&dict, &variant);
		dbus_message_iter_close_container(&array, &dict);
	dbus_message_iter_close_container(&iter, &array);

	e_dbus_message_send(conn, msg, get_contacts_count, -1, NULL);
	dbus_message_unref(msg);*/
}

void get_sms_results(void *data, DBusMessage *replymsg, DBusError *error)
{
	int co;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_INT32, &co, DBUS_TYPE_INVALID);

	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query_sms,
		"org.freesmartphone.PIM.MessageQuery",
		"GetMultipleResults"
	);
	dbus_message_append_args (msg, DBUS_TYPE_INT32, &co, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, populate_sms_table, -1, NULL);
	dbus_message_unref(msg);
	//show sms received indicator for new meesages : TODO
}

void get_sms_query(void *data, DBusMessage *replymsg, DBusError *error)
{
	char q[255], *q_s=q;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_STRING, &q_s, DBUS_TYPE_INVALID);
	query_sms = strdup(q_s);

	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query_sms,
		"org.freesmartphone.PIM.MessageQuery",
		"GetResultCount"
	);
	e_dbus_message_send(conn, msg, get_sms_results, -1, NULL);
	dbus_message_unref(msg);
}

void get_sms_data(void)
{
	char k[255], *key = k;
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;

	printf("Getting SMS data..\n");
	//elm_win_title_set(win, "Getting SMS data..");
	
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		"/org/freesmartphone/PIM/Messages",
		"org.freesmartphone.PIM.Messages",
		"Query"
	);
	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	dbus_message_iter_close_container(&iter, &array);
	
	//key = "_float_gt_Timestamp";
	
	/*dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	//dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
		//dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			//dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &variant);
				//dbus_message_iter_append_basic(&variant, DBUS_TYPE_DOUBLE, &s_ts);
			//dbus_message_iter_close_container(&dict, &variant);
		//dbus_message_iter_close_container(&array, &dict);
	dbus_message_iter_close_container(&iter, &array);*/

	e_dbus_message_send(conn, msg, get_sms_query, -1, NULL);
	dbus_message_unref(msg);
}

void populate_calls_table(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter, array, dict, final, dict2;
	int type;
	char key_val[255];
	char *key = key_val;
	dbus_int32_t int_val;
	char val[255];
	char *str_val = val;
	_call_data Call;

	if (dbus_error_is_set(error)) {
		printf("Calls Data Error: %s - %s\n", error->name, error->message);
		return;
	}
	begin_transaction();
	//elm_win_title_set(win, "Updating Calls Data..");
	printf("Updating Calls Data..\n");
	if (!dbus_message_iter_init(replymsg, &array)) printf("Message has no arguments");
	if ((type = dbus_message_iter_get_arg_type (&array)) != DBUS_TYPE_INVALID) //array
		dbus_message_iter_recurse(&array, &dict); //dict entry as string
	while ((type = dbus_message_iter_get_arg_type (&dict)) != DBUS_TYPE_INVALID) {
		Call.duration = 0; //to cater for calls where duration is not set
		dbus_message_iter_recurse(&dict, &iter);
		//while (dbus_message_iter_has_next(&iter)) {
		while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
			dbus_message_iter_recurse(&iter, &dict2);
			dbus_message_iter_get_basic(&dict2, &key);
			dbus_message_iter_next(&dict2);
			dbus_message_iter_recurse(&dict2, &final); 
			if ((type = dbus_message_iter_get_arg_type (&final)) == DBUS_TYPE_STRING)
				dbus_message_iter_get_basic(&final, &str_val);
			else if ((type = dbus_message_iter_get_arg_type (&final)) == DBUS_TYPE_INT32)
				dbus_message_iter_get_basic(&final, &int_val);
			if (strcmp(key, "Peer") == 0) strcpy(Call.peer, str_val);
			if (strcmp(key, "Timestamp") == 0) Call.timestamp = int_val;
			if (strcmp(key, "Direction") == 0) strcpy(Call.direction, str_val);
			if (strcmp(key, "Duration") == 0) Call.duration = int_val;
			if (strcmp(key, "Answered") == 0) Call.ans = int_val;
			if (strcmp(key, "Replied") == 0) Call.replied = int_val;
			if (strcmp(key, "New") == 0) Call.new_call = int_val;
			if (strcmp(key, "Path") == 0) strcpy(Call.path, str_val);
			dbus_message_iter_next(&iter); //while part
		}
		//peer, timestamp, direction, duration, ans, replied, new
		insert_calls_data(&Call);
		dbus_message_iter_next(&dict);
	}
	commit_transaction();
	//delete the query object
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query_calls,
		"org.freesmartphone.PIM.CallQuery",
		"Dispose"
	);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	match_call_names();
	update_calls_timestamp();
}

void get_call_results(void *data, DBusMessage *replymsg, DBusError *error)
 {
 	int co;

	 if (dbus_error_is_set(error)) {
 		printf("Error: %s - %s\n", error->name, error->message);
 	}
 	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_INT32, &co, DBUS_TYPE_INVALID);
	if (co > 75) co = 75;
 	DBusMessage *msg;
 	msg = dbus_message_new_method_call(
 		"org.freesmartphone.opimd",
 		query_calls,
 		"org.freesmartphone.PIM.CallQuery",
 		"GetMultipleResults"
 	);
 	dbus_message_append_args (msg, DBUS_TYPE_INT32, &co, DBUS_TYPE_INVALID);
 	e_dbus_message_send(conn, msg, populate_calls_table, -1, NULL);
 	dbus_message_unref(msg);
 }

void get_call_query(void *data, DBusMessage *replymsg, DBusError *error)
{
	char q[255], *q_c=q;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_STRING, &q_c, DBUS_TYPE_INVALID);
	query_calls = strdup(q_c);

	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query_calls,
		"org.freesmartphone.PIM.CallQuery",
		"GetResultCount"
	);
	e_dbus_message_send(conn, msg, get_call_results, -1, NULL);
	dbus_message_unref(msg);
}

void get_calls_data(void)
{
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;
	char k[255], *key = k, v[255], *val = v;
	int int_val;
	
	//elm_win_title_set(win, "Getting Calls data..");
	printf("Getting Calls data..\n");
	
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		"/org/freesmartphone/PIM/Calls",
		"org.freesmartphone.PIM.Calls",
		"Query"
	);

	/*dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	dbus_message_iter_close_container(&iter, &array);*/
	
	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	
		/*key = "_float_gt_Timestamp";
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_DOUBLE, &c_ts);
			dbus_message_iter_close_container(&dict, &variant);*/
		key="_sortby";
		val = "Timestamp";
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
			dbus_message_iter_close_container(&dict, &variant);
		key="_sortdesc";
		int_val = 1;
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
			dbus_message_iter_close_container(&dict, &variant);
		key="_limit";
		int_val = 75;
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
			dbus_message_iter_close_container(&dict, &variant);
	
		dbus_message_iter_close_container(&array, &dict);
	dbus_message_iter_close_container(&iter, &array);

	e_dbus_message_send(conn, msg, get_call_query, -1, NULL);
	dbus_message_unref(msg);
}

void del_single_sms(_sms_re *bb)
{
	//del sms from opim
	del_sms(bb->path);
	//del sms from sms table
	del_sms_path(bb->path);
	//delete the bubble and button
	evas_object_del(bb->bb);
	evas_object_del(bb->fwd_bt);
	evas_object_del(bb->del_bt);
	if (bb->ret_bt) evas_object_del(bb->ret_bt);
	//refresh conversation list
	add_sms_conv(conv_list);
}

void del_sms_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
}
void del_sms(char *pa)
{
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		pa,
		"org.freesmartphone.PIM.Message",
		"Delete"
	);
	e_dbus_message_send(conn, msg, del_sms_cb, -1, NULL);
	dbus_message_unref(msg);
}

void sms_sent_opim(void)
{
	char k[255], *key = k, pa[255];
	int int_val;
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;
	
	strcpy(pa, add_sms_path);
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		pa,
		"org.freesmartphone.PIM.Message",
		"Update"
	);

	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
	dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	
	key = "MessageSent"; int_val = 1;
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
			dbus_message_iter_close_container(&dict, &variant);
	key = "Processing"; int_val = 0;
		dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
			dbus_message_iter_close_container(&dict, &variant);
	
		dbus_message_iter_close_container(&array, &dict);
	dbus_message_iter_close_container(&iter, &array);

	//TODO:check callback
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
	sms_sent_db(pa);
}

//Re.from = 0 if reply from quick reply bb
//Re.from = 1 if reply from new sms originating from contact / phonelog action
//Re.from = 2 if retrying to send sms
void get_sms_sent_ack (void *data, DBusMessage *replymsg, DBusError *error)
{
	int index, flag=0;
	char ti[255], *time_s = ti, buf[255];

	flag = (void *)data;
	if (dbus_error_is_set(error)) { //message not sent
		printf("Error: %s - %s\n", error->name, error->message);		
		if(Re.from == 0) {
			bb_count ++;
			add_sent_sms(bb_count, 1, flag);
			elm_entry_entry_set(Re.en, "");
		}		
	}
	else { //message sent
		if (Re.from == 2) strcpy(add_sms_path, Re.path);		
		sms_sent_opim();
		dbus_message_get_args(replymsg, NULL, DBUS_TYPE_INT32, &index, DBUS_TYPE_STRING, &time_s, DBUS_TYPE_INVALID);
		printf("Message Index: %d", index);
		if(Re.from == 0) {
			bb_count ++;
			add_sent_sms(bb_count, 0, flag);
			//elm_entry_entry_set(Re.en, "");
			evas_object_del(send_bb);
		}
		if(Re.from != 1) { //change the quick re / this sms icon to normal
			snprintf(buf, sizeof(buf), "%s/sms_out.png", "/usr/share/launcher");
			elm_icon_file_set(Re.ic, buf, NULL);	
		}
		//update contact data for last contact
		update_contact_last("sms", Re.stamp, 1, Con_Sms[flag].name);
	}
	if(Re.from == 1) {
		evas_object_del(win_new_sms);
		sms_app(NULL, NULL, NULL);
	}
}

void reply_sms(void *data, Evas_Object *obj, void *event_info)
{
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;
	char p_num[255], *num = p_num, k[255], *key = k, val[255], *value = val, m[255], *mess = m, tystr[255], *tok, buf[510], ty[255];
	int csm_id=0, csm_num=0, csm_seq=0, len=0, rem=0, i=0, n=0;

	if(count_sms_con == 0) count_sms_con = 1;
	//loop for the number of contacts the message is being sent to
	for(n=0; n<count_sms_con; n++) {
		//set the number
		strcpy(tystr, Con_Sms[n].p_no);
		if(strcmp(tystr, "none") == 0) return;
		if ((tok = strchr(tystr, ':'))) {
			tok ++;
			strcpy(ty, tok);
		}
		else strcpy(ty, tystr);
		num = ty;
		//set the message
		if (Re.from != 2) { //retry from conversation sms view
			sprintf(tystr, "%s", elm_entry_entry_get(Re.en));
			if(strlen(tystr) == 0) return;
		}		
		else strcpy(tystr, Re.content);
		mess = elm_entry_markup_to_utf8(tystr);
		len = strlen(mess);
		//set the icon
		snprintf(buf, sizeof(buf), "%s/sms_wait.png", "/usr/share/launcher");
		elm_icon_file_set(Re.ic, buf, NULL);
		if(len < 160) {
			if (Re.from != 2) add_sms_opim(n);
			msg = dbus_message_new_method_call(
				"org.freesmartphone.ogsmd",
				"/org/freesmartphone/GSM/Device",
				"org.freesmartphone.GSM.SMS",
				//"SendTextMessage" 
				"SendMessage"
			);
			key = "";
			value = "";
			dbus_message_iter_init_append(msg, &iter);
			dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &num); //append phone number
			dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &mess); //append message
			//dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &rep);
			dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
			dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
			dbus_message_iter_close_container(&iter, &array);

			e_dbus_message_send(conn, msg, get_sms_sent_ack, -1, (void *)n);
			dbus_message_unref(msg);
		}
		else {
			add_sms_opim(n); // wont this fit csm too??
			//spilt messages for CSM
			csm_num = len/160;
			rem = len%160;
			if(rem) csm_num++;
			csm_id = 1;
			strcpy(buf, mess);

			for (i=0; i<csm_num; i++) {
				//break up buf into peices 160 char in length
				tok = buf + (160 * i);
				strncpy(mess, tok, 160);
				mess[160] ='\0';
				msg = dbus_message_new_method_call(
					"org.freesmartphone.ogsmd",
					"/org/freesmartphone/GSM/Device",
					"org.freesmartphone.GSM.SMS",
					"SendMessage");

				dbus_message_iter_init_append(msg, &iter);
				dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &num); //append phone number
				dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &mess); //append message
				dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
				dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
			
				key = "csm_id";
					dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
						dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
							dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &csm_id);
						dbus_message_iter_close_container(&dict, &variant);
				key = "csm_num";
					dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
						dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
							dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &csm_num);
						dbus_message_iter_close_container(&dict, &variant);
				key = "csm_seq";
				csm_seq = i+1;
					dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
						dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
							dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &csm_seq);
						dbus_message_iter_close_container(&dict, &variant);

					dbus_message_iter_close_container(&array, &dict);
				dbus_message_iter_close_container(&iter, &array);

				e_dbus_message_send(conn, msg, get_sms_sent_ack, -1, (void *)n);
				dbus_message_unref(msg);
				printf("id:%d num:%d seq:%d mess:%s\n", csm_id, csm_num, csm_seq, mess);
			}//csm loop
		}//else
	}//for loop
}

void add_sms_opim_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	char m[255], m1[255];
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		sprintf(m, "Could not add sms to opim.");
		sprintf(m1, "Error: %s - %s\n", error->name, error->message);
		popup_message(m, m1, 1);
	}
	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_STRING, &add_sms_path, DBUS_TYPE_INVALID);
	//change reply message icon to normal
}

void add_sms_opim(int n)
{
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;
	char k[10][255], *key, v[9][255], *val, tystr[255], *ty;
	int int_val, i;

	time(&t);
	strcpy(k[0], "Recipient");
	strcpy(k[1], "Direction");
	strcpy(k[2], "Folder");
	strcpy(k[3], "Content");
	strcpy(k[4], "MessageSent");
	strcpy(k[5], "Processing");
	strcpy(k[6], "Source");
	strcpy(k[7], "Timestamp");
	strcpy(k[8], "Timezone");
	strcpy(k[9], "Combined");
	
	ty = strchr(Con_Sms[n].p_no, ':');
	if (ty) sprintf(v[0], "%s", Con_Sms[n].p_no);
	else sprintf(v[0], "tel:%s", Con_Sms[n].p_no);
	
	strcpy(v[1], "out");
	strcpy(v[2], "SMS");
	
	sprintf(tystr, "%s", elm_entry_entry_get(Re.en));
	strcpy(v[3], elm_entry_markup_to_utf8(tystr));
	strcpy(v[6], "SMS");
	//sprintf(v[7], "%ld", t);
	Re.stamp = t;
	strcpy(v[8], "+0000");
	
	//add mess to opim
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		"/org/freesmartphone/PIM/Messages",
		"org.freesmartphone.PIM.Messages",
		"Add"
	);
	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
		for(i=0; i<10; i++) {
			dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
			key = k[i];
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
			if ((i == 4) || (i == 5) || (i==7) || (i == 9)) {
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
				if ((i == 4) || (i == 9)) int_val = 0;
				else if (i == 5) int_val = 1;
				else if (i == 7) int_val = t;
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
			}
			else {
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
				val = v[i];
				dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
			}
			dbus_message_iter_close_container(&dict, &variant);
			dbus_message_iter_close_container(&array, &dict);
			dbus_message_iter_close_container(&iter, &array);
		}

	e_dbus_message_send(conn, msg, add_sms_opim_cb, -1, NULL);
	dbus_message_unref(msg);
}                                                                                                                                                          

void add_contact_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	char p[255], m[255];
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		sprintf(p, "Error: %s", error->name);
		sprintf(m, "%s", error->message);
		popup_message(p, m, 1);
		evas_object_del(add_con_win);
	}
	else {
		evas_object_del(add_con_win);
		if (strcmp(con_save.action, "Add to Contacts") == 0) {
			evas_object_del(act_win);
			get_calls();
		}
		else if (strcmp(con_save.action, "Add to Contacts SMS") == 0) {
			evas_object_del(add_con_win);
			//refresh sms bubble names
			//refresh sms conv list
		}
		else populate_contact_list();
		popup_message("Contact Saved.", NULL, 1);
	}
}

void update_contact_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	//cater for contact from log
	char nam[255], phon[255], tystr[255], *tok, m[255], m1[255];

	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		sprintf(m, "Error: %s", error->name);
		sprintf(m1, "%s", error->message);
		popup_message(m, m1, 1);
	}
	else {
		sprintf(tystr, "%s", elm_entry_entry_get(con_save.name_en));
		tok = strtok(tystr, "<");
		strcpy(nam, tok);
		sprintf(tystr, "%s", elm_entry_entry_get(con_save.num_en));
		tok = strtok(tystr, "<");
		strcpy(phon, "tel:");
		strcat(phon, tok);
		//update the database
		update_contact_db(nam, phon, con_save.path); //repopulates contact list too
		popup_message("Contact changes Saved.", NULL, 1);
	}
	evas_object_del(add_con_win);
	evas_object_del(act_win);
}

void save_contact(void *data, Evas_Object *obj, void *event_info)
{
	char k[255], *key= k, v[255], *val=v, nam[255], phon[255], tystr[255], *tok;
	DBusMessage *msg;
	DBusMessageIter iter, array, dict, variant;

	//remove <br> from entry end
	sprintf(tystr, "%s", elm_entry_entry_get(con_save.name_en));
	tok = strtok(tystr, "<");
	strcpy(nam, tok);
	sprintf(tystr, "%s", elm_entry_entry_get(con_save.num_en));
	tok = strtok(tystr, "<");
	strcpy(phon, "tel:");
	strcat(phon, tok);
	update_call_db(nam, phon);
	
	if ((strcmp(con_save.action, "Add to Contacts") == 0) || (strcmp(con_save.action, "new") == 0) ||
		(strcmp(con_save.action, "Add to Contacts SMS") == 0)) {
		msg = dbus_message_new_method_call(
			"org.freesmartphone.opimd",
			"/org/freesmartphone/PIM/Contacts",
			"org.freesmartphone.PIM.Contacts",
			"Add"
		);
		dbus_message_iter_init_append(msg, &iter);
		dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
		key = "Name";
		val = nam;	
		dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
				dbus_message_iter_close_container(&dict, &variant);
			dbus_message_iter_close_container(&array, &dict);
		key = "Phone";
		val = phon;
		dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
				dbus_message_iter_close_container(&dict, &variant);
			dbus_message_iter_close_container(&array, &dict);	
		dbus_message_iter_close_container(&iter, &array);
		e_dbus_message_send(conn, msg, add_contact_cb, -1, NULL);
		dbus_message_unref(msg);
	}

	if (strcmp(con_save.action, "Edit Contact") == 0) {
		msg = dbus_message_new_method_call(
			"org.freesmartphone.opimd",
			con_save.path,
			"org.freesmartphone.PIM.Contact",
			"Update"
		);
		dbus_message_iter_init_append(msg, &iter);
		dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
		
		key = "Name";
		val = nam;	
		dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
				dbus_message_iter_close_container(&dict, &variant);
			dbus_message_iter_close_container(&array, &dict);
		key = "Phone";
		val = phon;
		dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
				dbus_message_iter_close_container(&dict, &variant);
			dbus_message_iter_close_container(&array, &dict);
		dbus_message_iter_close_container(&iter, &array);
		e_dbus_message_send(conn, msg, update_contact_cb, -1, NULL);
		dbus_message_unref(msg);
	}
}

void del_contact_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	popup_message("Contact Deleted", NULL, 1);
	evas_object_del(act_win);
}

void del_contact(char *path)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		path,
		"org.freesmartphone.PIM.Contact",
		"Delete"
	);
	e_dbus_message_send(conn, msg, del_contact_cb, -1, NULL);
	dbus_message_unref(msg);
	del_contact_db(path);
}

void del_log_entry_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	popup_message("Contact Deleted", NULL, 1);
	evas_object_del(act_win);
}

void del_log_entry(char *path)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		path,
		"org.freesmartphone.PIM.Call",
		"Delete"
	);
	e_dbus_message_send(conn, msg, del_log_entry_cb, -1, NULL);
	dbus_message_unref(msg);
	del_log_entry_db(path);
}

char (*clear_log_paths)[255]=NULL;  //declare and init dynamic array

void clear_log_opim_clear(void)
{
	//loop and delete the entries
	int i;
	for (i=0; i<no_log;i++){
		//printf("%s\n", clear_log_paths[i]);
		DBusMessage *msg;
		msg = dbus_message_new_method_call(
			"org.freesmartphone.opimd",
			clear_log_paths[i],
			"org.freesmartphone.PIM.Call",
			"Delete"
		);
		e_dbus_message_send(conn, msg, NULL, -1, NULL);
	}
	//free the dynamic array
	free(clear_log_paths);
}

void clear_log_opim_pop_arr(void *data, DBusMessage *replymsg, DBusError *error)
{
	//populate the array with the paths
	DBusMessageIter iter, array, dict, final, dict2;
	int type, i=0;
	char key_val[255];
	char *key = key_val;
	char val[255];
	char *str_val = val;

	if (dbus_error_is_set(error)) {
		printf("Calls Data Error: %s - %s\n", error->name, error->message);
		return;
	}

	if (!dbus_message_iter_init(replymsg, &array)) printf("Message has no arguments");
	if ((type = dbus_message_iter_get_arg_type (&array)) != DBUS_TYPE_INVALID) //array
		dbus_message_iter_recurse(&array, &dict); //dict entry as string
		while ((type = dbus_message_iter_get_arg_type (&dict)) != DBUS_TYPE_INVALID) {
			dbus_message_iter_recurse(&dict, &iter);
			while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
				dbus_message_iter_recurse(&iter, &dict2);
				dbus_message_iter_get_basic(&dict2, &key);
				dbus_message_iter_next(&dict2);
				dbus_message_iter_recurse(&dict2, &final); 
				if ((type = dbus_message_iter_get_arg_type (&final)) == DBUS_TYPE_STRING)
					dbus_message_iter_get_basic(&final, &str_val);
				if (strcmp(key, "Path") == 0) strcpy(clear_log_paths[i], str_val);
				dbus_message_iter_next(&iter); //while part
			}
			dbus_message_iter_next(&dict);
			i++;
		}

	//delete the query object
	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query_calls,
		"org.freesmartphone.PIM.CallQuery",
		"Dispose"
	);
	clear_log_opim_clear();
}
void clear_log_opim_results(void *data, DBusMessage *replymsg, DBusError *error)
{
	if (dbus_error_is_set(error)) {
 		printf("Error: %s - %s\n", error->name, error->message);
 	}
 	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_INT32, &no_log, DBUS_TYPE_INVALID);
 	DBusMessage *msg;
 	msg = dbus_message_new_method_call(
 		"org.freesmartphone.opimd",
 		query_calls,
 		"org.freesmartphone.PIM.CallQuery",
 		"GetMultipleResults"
 	);
 	dbus_message_append_args (msg, DBUS_TYPE_INT32, &no_log, DBUS_TYPE_INVALID);
 	e_dbus_message_send(conn, msg, clear_log_opim_pop_arr, -1, NULL);
 	dbus_message_unref(msg);
	//create the dynamic array
	clear_log_paths = calloc(no_log, sizeof(*clear_log_paths));
}

void clear_log_opim_count(void *data, DBusMessage *replymsg, DBusError *error)
{
	//get the no of entries
	char q[255], *q_c=q;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
	}
	dbus_message_get_args(replymsg, NULL, DBUS_TYPE_STRING, &q_c, DBUS_TYPE_INVALID);
	query_calls = strdup(q_c);

	DBusMessage *msg;
	msg = dbus_message_new_method_call(
		"org.freesmartphone.opimd",
		query_calls,
		"org.freesmartphone.PIM.CallQuery",
		"GetResultCount"
	);
	e_dbus_message_send(conn, msg, clear_log_opim_results, -1, NULL);
	dbus_message_unref(msg);
}

void clear_log_opim(void)
{	
	//direction == in && answered == 1
	if (strcmp(log_type, "Received") == 0) {
		DBusMessage *msg;
		DBusMessageIter iter, array, dict, variant;
		char k[255], *key = k, v[255], *val = v;
		int int_val;
	
		msg = dbus_message_new_method_call(
			"org.freesmartphone.opimd",
			"/org/freesmartphone/PIM/Calls",
			"org.freesmartphone.PIM.Calls",
			"Query"
		);

		dbus_message_iter_init_append(msg, &iter);
		dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
			dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	
			key="Direction";
			val = "in";
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
				dbus_message_iter_close_container(&dict, &variant);
			key="Answered";
			int_val = 1;
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
				dbus_message_iter_close_container(&dict, &variant);
	
			dbus_message_iter_close_container(&array, &dict);
		dbus_message_iter_close_container(&iter, &array);

		e_dbus_message_send(conn, msg, clear_log_opim_count, -1, NULL);
		dbus_message_unref(msg);
	}

	//direction == out 
	if (strcmp(log_type, "Outgoing") == 0) {
		DBusMessage *msg;
		DBusMessageIter iter, array, dict, variant;
		char k[255], *key = k, v[255], *val = v;
	
		msg = dbus_message_new_method_call(
			"org.freesmartphone.opimd",
			"/org/freesmartphone/PIM/Calls",
			"org.freesmartphone.PIM.Calls",
			"Query"
		);

		dbus_message_iter_init_append(msg, &iter);
		dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
			dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	
			key="Direction";
			val = "out";
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
				dbus_message_iter_close_container(&dict, &variant);
	
			dbus_message_iter_close_container(&array, &dict);
		dbus_message_iter_close_container(&iter, &array);

		e_dbus_message_send(conn, msg, clear_log_opim_count, -1, NULL);
		dbus_message_unref(msg);
	}

	//direction == in && answered == 0
	if (strcmp(log_type, "Missed") == 0) {
		DBusMessage *msg;
		DBusMessageIter iter, array, dict, variant;
		char k[255], *key = k, v[255], *val = v;
		int int_val;
	
		msg = dbus_message_new_method_call(
			"org.freesmartphone.opimd",
			"/org/freesmartphone/PIM/Calls",
			"org.freesmartphone.PIM.Calls",
			"Query"
		);

		dbus_message_iter_init_append(msg, &iter);
		dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
			dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
	
			key="Direction";
			val = "in";
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &val);
				dbus_message_iter_close_container(&dict, &variant);
			key="Answered";
			int_val = 0;
			dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
				dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &variant);
					dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &int_val);
				dbus_message_iter_close_container(&dict, &variant);
	
			dbus_message_iter_close_container(&array, &dict);
		dbus_message_iter_close_container(&iter, &array);

		e_dbus_message_send(conn, msg, clear_log_opim_count, -1, NULL);
		dbus_message_unref(msg);
	}
}

void get_brightness_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		return;
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
    dbus_message_iter_get_basic(&iter, &brightness);
}

void get_gsm_status_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		return;
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	dbus_message_iter_get_basic(&iter, &GSM_st);
}

void get_wifi_status_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		return;
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	dbus_message_iter_get_basic(&iter, &WiFi_st);
}

void get_bt_status_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter;
	
	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		return;
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	dbus_message_iter_get_basic(&iter, &bt_st);
}

void get_gps_status_cb(void *data, DBusMessage *replymsg, DBusError *error)
{
	DBusMessageIter iter;

	if (dbus_error_is_set(error)) {
		printf("Error: %s - %s\n", error->name, error->message);
		return;
	}
	if (!dbus_message_iter_init(replymsg, &iter)) printf("Message has no arguments");
	dbus_message_iter_get_basic(&iter, &GPS_st);
}

//get brightness value
void get_brightness(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.odeviced",
		"/org/freesmartphone/Device/Display/0", 
		"org.freesmartphone.Device.Display",
		"GetBrightness"); 
	e_dbus_message_send(conn, msg, get_brightness_cb, -1, NULL);
	dbus_message_unref(msg);
}

//set brightness value
void set_brightness(void *data, Evas_Object *obj, void *event_info)
{
    Evas_Object *sl = data;
    int value = (int)elm_slider_value_get(sl);
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.odeviced",
		"/org/freesmartphone/Device/Display/0", 
		"org.freesmartphone.Device.Display",
		"SetBrightness");
	dbus_message_append_args (msg, DBUS_TYPE_INT32, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
	brightness = value;
}

//get GSM status
void get_gsm_status(void)
{
    char *value;
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.ousaged",
		"/org/freesmartphone/Usage", 
		"org.freesmartphone.Usage",
		"GetResourceState");
	value = "GSM";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, get_gsm_status_cb, -1, NULL);
	dbus_message_unref(msg);
}

//set gsm status
void enable_gsm(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.ogsmd",
		"/org/freesmartphone/GSM/Device", 
		"org.freesmartphone.Resource",
		"Enable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void disable_gsm(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.ogsmd",
		"/org/freesmartphone/GSM/Device", 
		"org.freesmartphone.Resource",
		"Disable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void gsm_set(void *data, Evas_Object *obj, void *event_info)
{
    Evas_Object *tg = (Evas_Object *)data;
    int state = elm_toggle_state_get(tg);
    if (state) enable_gsm();
    else disable_gsm();
}

//get Wifi status
void get_wifi_status(void)
{
	DBusMessage *msg;
	char *value;
	
	msg = dbus_message_new_method_call("org.freesmartphone.ousaged",
		"/org/freesmartphone/Usage", 
		"org.freesmartphone.Usage",
		"GetResourceState");
	value = "WiFi";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, get_wifi_status_cb, -1, NULL);
	dbus_message_unref(msg);
}

//set Wifi status
void enable_wifi(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.odeviced",
		"/org/freesmartphone/Resource/WiFi", 
		"org.freesmartphone.Resource",
		"Enable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void disable_wifi(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.odeviced",
		"/org/freesmartphone/Resource/WiFi", 
		"org.freesmartphone.Resource",
		"Disable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void wifi_set(void *data, Evas_Object *obj, void *event_info)
{
    Evas_Object *tg = (Evas_Object *)data;
    int state = elm_toggle_state_get(tg);
    if (state) enable_wifi();
    else disable_wifi();
}

//get bt status
void get_bt_status(void)
{
	DBusMessage *msg;
	char *value;
	
	msg = dbus_message_new_method_call("org.freesmartphone.ousaged",
		"/org/freesmartphone/Usage", 
		"org.freesmartphone.Usage",
		"GetResourceState");
	value = "Bluetooth";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, get_bt_status_cb, -1, NULL);
	dbus_message_unref(msg);
}

//set bt status
void enable_bt(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.odeviced",
		"/org/freesmartphone/Resource/Bluetooth", 
		"org.freesmartphone.Resource",
		"Enable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void disable_bt(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.odeviced",
		"/org/freesmartphone/Resource/Bluetooth", 
		"org.freesmartphone.Resource",
		"Disable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void bt_set(void *data, Evas_Object *obj, void *event_info)
{
    Evas_Object *tg = (Evas_Object *)data;
    int state = elm_toggle_state_get(tg);
    if (state) enable_bt();
    else disable_bt();
}

//get gps status
void get_gps_status(void)
{
	DBusMessage *msg;
	const char *value;
	msg = dbus_message_new_method_call("org.freesmartphone.ousaged",
		"/org/freesmartphone/Usage", 
		"org.freesmartphone.Usage",
		"GetResourceState");
	value = "GPS";
	dbus_message_append_args (msg, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
	e_dbus_message_send(conn, msg, get_gps_status_cb, -1, NULL);
	dbus_message_unref(msg);
}

//set gps status
void enable_gps(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.ogpsd",
		"/org/freedesktop/Gypsy", 
		"org.freesmartphone.Resource",
		"Enable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void disable_gps(void)
{
	DBusMessage *msg;
	
	msg = dbus_message_new_method_call("org.freesmartphone.ogpsd",
		"/org/freedesktop/Gypsy", 
		"org.freesmartphone.Resource",
		"Disable");
	e_dbus_message_send(conn, msg, NULL, -1, NULL);
	dbus_message_unref(msg);
}

void gps_set(void *data, Evas_Object *obj, void *event_info)
{
    Evas_Object *tg = (Evas_Object *)data;
    int state = elm_toggle_state_get(tg);
    if (state) enable_gps();
    else disable_gps();
}
